﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core;
using COFE.Core.Profile;
using COFE.Core.Utils;
using COFE.Core.Entry;

namespace COFE.Core.Lister
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="R">Root type, which is a directory.</typeparam>
    /// <typeparam name="T">Folder/File type</typeparam>
    public abstract class SecondaryDirectoryListerBase<T> : DirectoryListerBase<T>, ISecondaryDirectoryLister
    {

        #region Constructor

        protected SecondaryDirectoryListerBase(IFactory<IDirectoryLister> factory, string listerKey)
            : base(factory, listerKey)
        {
            _supportedPattern = _getSupportedPathPatterns();
        }

        #endregion

        #region Methods

        public override IEnumerable<IFileSystemInfo> List(IInternalDirectoryInfoExA parent, EntryConstructionFlags flags)
        {
            string parentParseName = parent.GetParseNameOrDefault();
            T parentEntry = getEmbeddedItem(parent);
            IEnumerator<T> etor = _list(getEmbeddedItem(parent)).GetEnumerator();
            while (etor.MoveNext())
                yield return COFEShared.EntryConstructor.CreateEntry(ListerKey,
                    CreatePropertyProvider(etor.Current), EntryConstructionFlags.DefaultWithoutCache);
        }

        public virtual IPropertyProvider ConvertEntry(
            IPropertyProvider primPropProvider, EntryConstructionFlags flags)
        {
            if (primPropProvider == null)
                return null;

            var retEntry = ConvertEntry(COFEShared.EntryConstructor
                .CreateEntry(primPropProvider,
                flags ^ EntryConstructionFlags.ConvertEntry));
            
            if (retEntry == null)
                return null;
            else return retEntry.InternalProperties.PrimaryPropertyProvider;
        }

        public virtual IInternalFileSystemInfoExA ConvertEntry(IInternalFileSystemInfoExA item)
        {
            T convertedItem = _convertEntry(item);
            if (convertedItem != null)
                return COFEShared.EntryConstructor.CreateDirectory(this.ListerKey, CreatePropertyProvider(convertedItem), EntryConstructionFlags.DefaultWithoutCache);
            return null;
        }

        public IEnumerable<IInternalFileSystemInfoExA> AppendEntries(IInternalDirectoryInfoExA parent)
        {
            string parentParseName = parent.GetParseNameOrDefault();
            IEnumerator<T> etor = _appendEntries(parent).GetEnumerator();
            while (etor.MoveNext())
                if (_isDirectory(etor.Current))
                    yield return COFEShared.EntryConstructor.CreateDirectory(ListerKey, CreatePropertyProvider(etor.Current));
                else yield return COFEShared.EntryConstructor.CreateFile(ListerKey, CreatePropertyProvider(etor.Current));
        }

        public IInternalDirectoryInfoExA CreateVirtualDirectory(IInternalDirectoryInfoExA parent, string dirName, string type)
        {
            string parentParseName = parent.GetParseNameOrDefault();
            T createdDirectory = _createVirtualDirectory(parent, dirName, type);
            if (createdDirectory != null)
                return COFEShared.EntryConstructor.CreateDirectory(ListerKey, CreatePropertyProvider(createdDirectory));
            return null;
        }


        #endregion

        #region Data

        private string[] _supportedPattern = new string[] { };

        protected Func<string[]> _getSupportedPathPatterns = () => { return new string[] { }; };
        protected Func<IInternalFileSystemInfoExA, T> _convertEntry = (entry) => { return default(T); };
        protected Func<IInternalDirectoryInfoExA, IEnumerable<T>> _appendEntries = (dir) => { return new List<T>(); };
        protected Func<IInternalDirectoryInfoExA, string, string, T> _createVirtualDirectory = (item, name, type) => { return default(T); };

        #endregion

        #region Public Properties

        public string[] ConvertableFileNamePatterns { get { return _supportedPattern; } }


        #endregion




    }
}
